package datastore.db;

import org.apache.commons.lang.builder.ToStringBuilder;

public class Query<M extends Model> extends BaseQuery<M> {

    /*
     * An application creates a Query object either by calling the constructor with the Model class whose entities are
     * to be queried, or by calling the class's all() class method.
     * 
     * class Song(db.Model): title = db.StringProperty() composer = db.StringProperty() date = db.DateTimeProperty()
     * 
     * query = db.Query(Song)
     * 
     * query = Song.all()
     * 
     * Without modification, the object represents a query for all entities of the given kind. Method calls customize
     * the query with property conditions (filter()), ancestor conditions (ancestor()), and ordering (order()). For
     * convenience, these methods return self so that they can be chained together in a single statement.
     * 
     * query.filter('title =', 'Imagine') query.order('-date') query.ancestor(key)
     * 
     * query.filter('title =', 'Imagine').order('-date').ancestor(key)
     * 
     * The application executes the query in one of two ways:
     * 
     * 
     * 
     * by calling the fetch() method. This performs a single call to the datastore to fetch results, up to the specified
     * number of results. The Query object does not cache results, so calling fetch() a second time will re-execute the
     * query.
     * 
     * results = query.fetch(limit=5) for song in results: print song.title
     * 
     * 
     * 
     * by treating the Query object as an iterable. The iterator retrieves results from the datastore in small batches,
     * allowing for the app to stop iterating on results to avoid fetching more than is needed. Iteration stops when all
     * of the results that match the query have been retrieved. As with fetch(), the iterator interface does not cache
     * results, so creating a new iterator from the Query object will re-execute the query.
     * 
     * for song in query: print song.title
     * 
     * See also GqlQuery, a query class that uses a SQL-like query language.
     * 
     * Note: The index-based data structures and algorithms that power datastore queries do not support some kinds of
     * queries. See Queries and Indexes: Restrictions on Queries for more information. Constructor
     * 
     * The constructor of the Query class is defined as follows:
     * 
     * class Query(model_class)
     * 
     * A datastore query interface that uses objects and methods to prepare queries.
     * 
     * The Query instance returned by the constructor represents a query for all entities of the kind.
     * 
     * Arguments:
     * 
     * model_class The class of the Model (or Expando) that represents the datastore entity kind for the query.
     */

    /**
     * A datastore query interface that uses objects and methods to prepare queries. The instance methods filter(),
     * order() and ancestor() apply criteria to the query to filter or order the results.
     * @throws Exception 
     * @throws SecurityException 
     */
    public Query(Class<M> modelClass) {
       super(modelClass);
    }

    @SuppressWarnings("unchecked")
    public Query(String className) throws Exception {
        super((Class<M>) Class.forName(className));
    }
    /*
     * Instance Methods
     * 
     * Instances of the Query class have the following methods:
     * 
     * filter(property_operator, value)
     * 
     * Adds a property condition filter to the query. Only entities with properties that meet all of the conditions will
     * be returned by the query.
     * 
     * Arguments:
     * 
     * property_operator A string containing the property name, and an optional comparison operator. The name and the
     * operator must be separated by a space, as in: age > The following comparison operators are supported: < <= = >= >
     * != IN If the operator is omitted from the string (the argument is just the property name), the filter uses the =
     * operator. value The value to use in the comparison on the right-hand side of the expression. Its type should be
     * the value data type for the property being compared. See Types and Property Classes.
     * 
     * query.filter('height >', 42).filter('city = ', 'Seattle')
     * 
     * query.filter('user = ', users.get_current_user())
     */
    public Query<M> filter(String propertyOperator, Object value) {
        throw new UnsupportedOperationException();
    }

    /* order(property)
     * 
     * Adds an ordering for the results. Results are ordered starting with the first order added.
     * 
     * Arguments:
     * 
     * property A string, the name of the property to order. To specify that the order ought to be in descending order,
     * precede the name with a hyphen (-). Without a hyphen, the order is ascending.
     * 
     * # Order by last name, alphabetical: query.order('last_name')
     * 
     * # Order tallest to shortest: query.order('-height')
     */
    public Query<M> order(String property) {
        throw new UnsupportedOperationException();
    }

    /* ancestor(ancestor)
     * 
     * Adds an ancestor condition filter to the query. Only entities with the given entity as an ancestor (anywhere in
     * its path) will be returned by the query.
     * 
     * Arguments:
     * 
     * ancestor A Model instance or Key instance representing the ancestor.
     */
    public Query<M> ancestor(Model ancestor) {
        throw new UnsupportedOperationException();
    }

    public Query<M> ancestor(Key ancestorKey) {
        throw new UnsupportedOperationException();
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}
